#include "stdafx.h"
#include "NativeChessEngine.h"
#include "Board.h"
#include <memory>
#include "BasicStrategy.h"
#include "MoveGenerator.h"

using namespace std;

struct EngineContext 
{
	shared_ptr<Board> Board;
	Strategy::Ptr BlackStrategy, WhiteStrategy;
};

ENGINE_INTEROP(void) Engine_SetStrategies(EngineContext *context, const char *blackStrategy, const char *whiteStrategy)
{
	if (strcmp(blackStrategy, "basic") == 0)
		context->BlackStrategy = make_shared<BasicStrategy>();
	if (strcmp(whiteStrategy, "basic") == 0)
		context->WhiteStrategy = make_shared<BasicStrategy>();
}

ENGINE_INTEROP(EngineContext*) Engine_StartGame(const char *fen, const char *blackStrategy, const char *whiteStrategy)
{
	EngineContext *context = new EngineContext;
	context->Board = make_shared<Board>(fen);

	Engine_SetStrategies(context, blackStrategy, whiteStrategy);

	return context;
}

ENGINE_INTEROP(EngineContext*) Engine_StartDefaultGame(const char *blackStrategy, const char *whiteStrategy)
{
	EngineContext *context = new EngineContext;
	context->Board = make_shared<Board>(true);

	Engine_SetStrategies(context, blackStrategy, whiteStrategy);

	return context;
}

ENGINE_INTEROP(void) Engine_DoMove(EngineContext *context, Move move)
{
	context->Board->DoMove(move);
}

ENGINE_INTEROP(Move) Engine_AIMove(EngineContext *context)
{
	Move m;

	switch (context->Board->WhoseMove)
	{
	case PieceColor::Black:
		m = context->BlackStrategy->GetNextMove(*context->Board);
		break;
	case PieceColor::White:
		m = context->WhiteStrategy->GetNextMove(*context->Board);
		break;
	}

	//Engine_DoMove(context, m);

	return m;
}

ENGINE_INTEROP(void) Engine_GetMoves(EngineContext *context, Move **moves, int *numMoves)
{
	std::vector<Move> vmoves;
	MoveGenerator().Generate(*context->Board, nullptr, vmoves);

	if (!vmoves.empty())
	{
		*moves = new Move[vmoves.size()];
		memcpy(*moves, &vmoves[0], sizeof(Move) * vmoves.size());
	}

	*numMoves = vmoves.size();
}

ENGINE_INTEROP(void) Engine_FreeMoves(Move *moves)
{
	delete [] moves;
}

ENGINE_INTEROP(void) Engine_GetBoardState(EngineContext *context, Piece *squares, uint *flags, PieceColor *whoseMove)
{
	memcpy(squares, context->Board->Squares, sizeof(Piece) * NUM_SQUARES);

	*flags = context->Board->CurrentState;
	*whoseMove = context->Board->WhoseMove;
}

ENGINE_INTEROP(void) Engine_Free(EngineContext *context)
{
	delete context;
}

